AddCSLuaFile( "cl_init.lua" )
AddCSLuaFile( "shared.lua" )


include('shared.lua')

ENT.WireDebugName = "Clientside Lua"

local MODEL = Model("models/cheeze/wires/cpu.mdl")

function ENT:Initialize()
	self.Entity:SetModel( MODEL )
	self.Entity:PhysicsInit( SOLID_VPHYSICS )
	self.Entity:SetMoveType( MOVETYPE_VPHYSICS )
	self.Entity:SetSolid( SOLID_VPHYSICS )
	self.VPos = Vector(0, 0, 0)

	self.Outputs = Wire_CreateOutputs( self.Entity, {} )
	self.Inputs = Wire_CreateInputs( self.Entity, {} )
	self.Lua = ""
	
	self:SetOverlayText( "Clientside Lua" )
end

function ENT:OnRemove() 
	//This removes cruft left over by various processes.
	if(WireClua.Ents[self.pl]) then
		WireClua.Ents[self.pl][self.Name]=nil
	end
end

function ENT:SetPuts(puts,inputs)
	local wireputs={}
	local prevvalues={}
	if(type(puts)=="table") then
		//How nice, it is already dealt with.
		local name
		for putstr,info in pairs(puts) do
			//This tests if it starts with a number, which I am guessing is bad since it is not allowed in the expression chip.
			if(tonumber(string.sub(putstr,1,1))==nil) then
				putstr=string.lower(putstr)
				//String manipulation formats it into starting with an upper case character.
				name=string.upper(string.sub(putstr,1,1))..string.lower(string.sub(putstr,2))
				table.insert(wireputs,name)
				if(inputs!=true) then
					prevvalues[name]=info.Value
				end
			end
		end
	else
		//Gmatch will sort it all out, anything that is not alphanumeric is counted as a seperator.
		for putstr in string.gmatch(puts, "([%a%d]+)") do
			//This tests if it starts with a number, which I am guessing is bad since it is not allowed in the expression chip.
			if(tonumber(string.sub(putstr,1,1))==nil) then
				putstr=string.lower(putstr)
				//String manipulation formats it into starting with an upper case character.
				table.insert(wireputs,string.upper(string.sub(putstr,1,1))..string.lower(string.sub(putstr,2)))
			end
		end
	end
	
	if(inputs) then //If it says to be an input, then make it an input
		WireLib.AdjustInputs(self.Entity, wireputs)
	else
		WireLib.AdjustOutputs(self.Entity, wireputs)
		if(prevvalues!=nil) then
			//Previous values! Load them! This will prevent contraptions from crushing themselfs with 0 length hydraulics.
			for name,value in pairs(prevvalues) do
				Wire_TriggerOutput(self.Entity,name,value)
			end
		end
	end
end
//These are simple aliases that make it easier to deal with
function ENT:SetInputs(inputs)
	self:SetPuts(inputs,true)
end
function ENT:SetOutputs(outputs)
	self:SetPuts(outputs)
end


function ENT:SetNameC(name)
	if(WireClua.Ents[self.pl]==nil) then
		WireClua.Ents[self.pl]={}
	end
	if(self.Name) then
		WireClua.Ents[self.pl][self.Name]=nil
	end
	WireClua.Ents[self.pl][name]=self
	
	self.Name=name
	
	timer.Simple(.3,WireClua.SetNameC,self.pl,name,self)
	self:UpdateOverlay()
end

function ENT:SetLua(lua)
	if(WireClua.EnableLua!=true) then return end
	//Tell the client about the incoming download.
	//If this is delayed it won't work.
	umsg.Start("WireClua.RecieveDownloadInfo",self.pl)
		umsg.Entity(self)
		umsg.Long(id)
	umsg.End()

	self.Lua=lua
	local id=tls.InitDL(self.pl,lua,"WireClua_SetLua")
	self:UpdateOverlay()
end


function ENT:ReloadLua()
	umsg.Start("WireClua.ReloadLua",self.pl)
		umsg.Entity(self)
	umsg.End()
end

function ENT:UpdateOverlay()
	local overlay=""
	if(self.Name and self.Name!="") then
		overlay=overlay..self.Name.."\n"
	end
	if(self.Lua!="") then
		overlay=overlay.."Lua embedded\n"
	end
	overlay=overlay.."Clientside Lua"
	self:SetOverlayText(overlay)
end

/*
function ENT:ShowOutput(value)
	if value ~= self.PrevOutput then
		self:SetOverlayText( "Clua" )
		self.PrevOutput = value
	end
end
*/

function ENT:OnRestore()
	self.BaseClass.OnRestore(self)
end

function ENT:TriggerInput(iname, value)
	if(iname==nil) then
		return
	end
	//Excess lag, not needed as well
	//iname=string.gsub(string.lower(iname),"[^%a%d]","")
	value=tostring(tonumber(value) or 0)
	//There is no way for anything bad to fall through this. Everything gets verified several times.
	umsg.Start("WireClua.Msg",self.pl)
		umsg.String(string.lower(iname))
		umsg.Float(value)
		umsg.Entity(self)
	umsg.End()
end

function ENT:GetBeaconPos(sensor)
	return self.VPos
end


function ENT:BuildDupeInfo()
	local info = self.BaseClass.BuildDupeInfo(self) or {}
	info.Lua=tls.encode(self.Lua)
	
	return info
end

function ENT:ApplyDupeInfo(ply, ent, info, GetEntByID)
	if(info.Lua!="") then
		timer.Simple(.3,WireClua.SetLua,self,tls.decode(info.Lua))
	end
	self.BaseClass.ApplyDupeInfo(self, ply, ent, info, GetEntByID)
end